// Copyright (c) 2019 Presto Labs Pte. Ltd.
// Author: linchuan

#pragma once

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "coin2/exchange/base/symbology/spot_product.h"
#include "coin2/exchange/base/symbology/util.h"
#include "coin2/exchange/bithumb/symbology/currency.h"

namespace coin2::exchange::bithumb::symbology {

class BithumbProduct : public base::symbology::SpotProduct<BithumbCurrency, BithumbProduct>,
                       public base::symbology::ProductFromStrMixin<BithumbProduct> {
 public:
  typedef SpotProduct<BithumbCurrency, BithumbProduct> BaseProduct;

  BithumbProduct(const BithumbCurrency& base, const BithumbCurrency& quote)
      : SpotProduct(
            base,
            quote,
            ToBithumbNativeProduct(base, quote),
            ToBithumbNativeProduct(base, quote),
            base::market::ExchangeType::Bithumb) {}

 public:
  static std::unique_ptr<BithumbProduct> FromNativeStrImpl(
      const std::string& native_product,
      int64_t resolve_timestamp) {
    std::unique_ptr<BithumbCurrency> base_ptr;
    std::unique_ptr<BithumbCurrency> quote_ptr;
    bool success =
        ParseBithumbNativeProduct(native_product, resolve_timestamp, &base_ptr, &quote_ptr);
    if (success) {
      return std::make_unique<BithumbProduct>(*base_ptr, *quote_ptr);
    } else {
      return {};
    }
  }

 private:
  static bool ParseBithumbNativeProduct(
      const std::string& product_str,
      int64_t resolve_timestamp,
      std::unique_ptr<BithumbCurrency>* base_ptr,
      std::unique_ptr<BithumbCurrency>* quote_ptr) {
    using base::market::MarketType;
    using base::symbology::HasValue;

    const std::string& product_str_upper = StringToUpperCopy(product_str);
    std::vector<std::string> splitted;
    splitted = Split(product_str_upper, "_");
    if (splitted.size() == 1) {
      *base_ptr = BithumbCurrency::FromNativeStrNoThrow(splitted[0], resolve_timestamp);
      *quote_ptr = BithumbCurrency::FromNativeStrNoThrow("KRW", resolve_timestamp);
      return true;
    } else if (splitted.size() == 2) {
      *base_ptr = BithumbCurrency::FromNativeStrNoThrow(splitted[0], resolve_timestamp);
      *quote_ptr = BithumbCurrency::FromNativeStrNoThrow(splitted[1], resolve_timestamp);
      return true;
    } else {
      return false;
    }
  }

  static std::string ToBithumbNativeProduct(
      const BithumbCurrency& base,
      const BithumbCurrency& quote) {
    using base::market::MarketType;
    std::stringstream ss;
    ss << base.native_currency(MarketType::Spot) << '_' << quote.native_currency(MarketType::Spot);
    return ss.str();
  }
};

}  // namespace coin2::exchange::bithumb::symbology
